// AC_Lab002.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Utils.h"
#include "CMDLine.h"

#include "ASN1UTCTime.h"
#include "ASN1Bool.h"
#include "ASN1Null.h"
#include "ASN1OctectString.h"

#include "CertificateGenerator.h"
#include "Name.h"
#include "AlgorithmIdentifiers.h"
#include "Extensions.h"

#include "PKCSContentInfo.h"
#include "PKCSContent.h"
#include "PKCSSignedData.h"

#include <iostream>
#include <fstream>

using namespace AppliedCryptography;
using namespace CryptoPP;

namespace ac = AppliedCryptography;

std::string GenerateCert(int serialNumber, char* cn, char* o, char* c, char* startDate, char* endDate)
{
	CertificateGenerator cg;
	ac::Name issuer;
	ac::Name subject;
	ASN1PrintableString commonName,organization,country;
	ASN1UTCTime start, end; 
	ASN1Encoded privateKey, publicKey;
	std::vector<byte> certificate;
	Extensions extensions;
	ASN1Sequence valueCertifiedAuthority;
	ASN1OctectString valueBasicConstraints;

	valueCertifiedAuthority.add(ASN1Bool::True);
	valueBasicConstraints.set(valueCertifiedAuthority.encode());

	GetKeys(privateKey, publicKey);

	cg.setSerialNumber(1);
	cg.setIssuer(issuer
		.add(ac::Name::CN, commonName.set(cn))
		.add(ac::Name::O, organization.set(o))
		.add(ac::Name::C, country.set(c)));
	cg.setNotBefore(start.set(startDate));
	cg.setNotAfter(start.set(endDate));
	cg.setSubject(issuer);
	//cg.setSignatureAlgorithm(AlgorithmIdentifiers::md5WithRSAEncryption);
	cg.setSignatureAlgorithm(AlgorithmIdentifiers::sha1WithRSAEncryption);
	cg.setPublicKey(publicKey);
	cg.setExtensions(extensions.add(Extensions::BasicConstraintsOID, ASN1Bool::True, valueBasicConstraints));

	cg.generateSignature(privateKey);

	PKCSContentInfo ci;
	PKCSSignedData content;
	std::string res;

	ci.setContent(content.setCertificate(cg));

	//res = Vector2HexStr(ci.encode());
	return Vector2B64Str(ci.encode());
};

int main(int argc, char* argv[])
{
	std::ofstream file;

	std::cout << std::endl;

	if(argc <= 1)
	{
		PrintUsage(argv[0]);
		return 0;
	};

	if(strcmp(argv[1],"/test")==0)
	{
		::testing::InitGoogleMock(&argc, argv);
		return RUN_ALL_TESTS();
	}
	else if(strcmp(argv[1],"/gen") == 0 && argc == 9)
	{
		file.open(argv[2]);
		if(file.is_open())
		{
			file << "-----BEGIN CERTIFICATE-----\n";
			file << GenerateCert(atoi(argv[3]), argv[4], argv[5], argv[6], argv[7], argv[8]);
			file << "-----END CERTIFICATE-----\n";
			file.close();
		};
	}
	else
	{
		PrintUsage(argv[0]);
	};

	return 0;
}

